/***********************************************************
! @File        : downloadmanager.h
 *  @Brief       : 多段下载
 *  @Details     : 服务器要支持range，断点续传功能才可，通过将文件分成多个range，线程完成range的工作
 *  @Author      : soda
 *  @Date        : 2023-12-05 09:51:09
 *  @Version     : v1.0
 *  @Copyright   : Copyright By soda, All Rights Reserved
 ***********************************************************/

#ifndef DOWNLOADMANAGER_H
#define DOWNLOADMANAGER_H
#include <QtNetwork>
#include <QtCore>

typedef struct TaskInfo {
    int order = 0;              // 编号
    QUrl url;                   // url
    int startPos = -1;          // 起始下载位置
    int endPos = -1;            // 结束下载位置
    int haveBytes = 0;          // 下载的大小
    bool bFinish = false;       // 是否结束
    bool bRange = false;        // 是否是分段
} TaskInfo;


class DownloadTask : public QObject
{
    Q_OBJECT
public:
    DownloadTask(QObject* parent = 0)
    :QObject(parent){};
    ~DownloadTask() {};

    QNetworkReply* reply() { return m_reply; };

    void start(TaskInfo& task) {
        m_task = task;
        if(m_manager == nullptr)
            m_manager = new QNetworkAccessManager(this);
        QNetworkRequest request(m_task.url);
        if(m_task.bRange) {
            request.setRawHeader(QByteArray("Range"), QString("bytes=%1-%2").arg(m_task.startPos).arg(m_task.endPos).toLocal8Bit());
        }

        m_reply = m_manager->get(request);
        connect(m_reply, &QNetworkReply::readyRead, \
            this, [this](){ emit readyRead(m_task.order); }, Qt::QueuedConnection);
        connect(m_reply, &QNetworkReply::finished,
            this, [this](){ emit finished(m_task.order); }, Qt::QueuedConnection);
        connect(m_reply, &QNetworkReply::errorOccurred,
            this, [this](){ emit errorOccurred(m_task.order); }, Qt::QueuedConnection);
    }

signals:
    void finished(int order);
    void readyRead(int order);
    void errorOccurred(int order);

private:
    QNetworkAccessManager* m_manager = nullptr;
    QNetworkReply* m_reply  = nullptr;
    TaskInfo m_task;
};

class DownloadManager: public QObject
{
    Q_OBJECT
public:
    explicit DownloadManager(QObject *parent = nullptr);
    int calcFileSize(const QUrl &url);
    bool startDownload(const QUrl url, const QString path, int workNumber = 5);
signals:
    void finished();

public slots:
    void downloadReadyRead(int order);
    void downloadFinished(int order);
    void downloadError(int order);


//    void startNextDownload();
//    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
//    void downloadFinished();
//    void downloadReadyRead();

private:
    QVector<TaskInfo> m_vecData;
    QVector<DownloadTask*> m_vecTask;
    QElapsedTimer m_downloadTimer;
    QFile m_output;
    //int downloadedCount = 0;
    //int totalCount = 0;
};

#endif
